﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace ALinq.Mapping
{
    internal class ModelMappingCollection<TMapping, TKey> : IEnumerable<TMapping>, ICollection<TMapping>
        where TMapping : ModelMapping
    {
        private Dictionary<TKey, TMapping> items;
        private ModelMapping parent;
        private Func<TMapping, TKey> keyMember;
        public ModelMappingCollection(ModelMapping parent, Func<TMapping, TKey> keyMember)
        {
            this.parent = parent;

            items = new Dictionary<TKey, TMapping>();
            this.keyMember = keyMember;
        }

        public void Add(TMapping item)
        {
            Error.ValidateArgumentNotNull(() => item);
            var key = keyMember(item);
            items.Add(key, item);
            item.Parent = this.parent;
            //parent.XmlElement.AppendChild(item.XmlElement);
        }

        internal TMapping GetItem(TKey key)
        {
            TMapping item;
            if (items.TryGetValue(key, out item))
                return item;

            return null;
        }

        public void CopyTo(TMapping[] array, int arrayIndex)
        {
            items.Values.CopyTo(array, arrayIndex);
        }

        public bool Remove(TMapping item)
        {
            Error.ValidateArgumentNotNull(() => item);

            TKey key = keyMember(item);
            TMapping value;
            if (!items.TryGetValue(key, out value))
                throw Error.NotContainsItem();

            if (!items.Remove(key))
                return false;

            return true;
        }

        public int Count
        {
            get { return items.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public void Clear()
        {
            items.Clear();
            //parent.XmlElement.InnerXml = string.Empty;
        }

        public bool Contains(TMapping item)
        {
            return items.ContainsValue(item);
        }

        #region Implementation of IEnumerable

        public IEnumerator<TMapping> GetEnumerator()
        {
            return items.Values.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion
    }
}
